package com.ymt.bpm.service.platform.helper;

import com.alibaba.fastjson.JSONObject;
import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.WebResource;
import com.sun.jersey.api.client.filter.HTTPBasicAuthFilter;
import com.sun.jersey.client.apache.config.ApacheHttpClientConfig;
import com.sun.jersey.client.apache.config.DefaultApacheHttpClientConfig;
import com.sun.jersey.core.util.MultivaluedMapImpl;
import com.ymt.bpm.appboot.SpringContext;
import com.ymt.bpm.util.Const;

import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.UriBuilder;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Date;
import java.util.Map;
import java.util.Map.Entry;
import java.util.logging.Level;
import java.util.logging.Logger;

public class JerseyRestClient {

	private static Logger logger = Logger.getLogger(JerseyRestClient.class.getName());
	private Client client;


	public JerseyRestClient(String userName, String password) {

		int poolSize = 100; // connections
		int connectTimout = 10000;	//ms
		int readTimeout = 30000;
		int chunkSize = -1;

		if (SpringContext.getAppContext()!=null) {
			EnvironmentService es = SpringContext.getAppContext().getBean(EnvironmentService.class);
			poolSize = Integer.parseInt(es.getProperty("bpmp.httpclient.poolsize", "100")); // connections
			connectTimout = Integer.parseInt(es.getProperty("bpmp.httpclient.connect-timeout", "3000"));	//ms
			readTimeout = Integer.parseInt(es.getProperty("bpmp.httpclient.read-timeout", "20000"));	//ms
			chunkSize = Integer.parseInt(es.getProperty("bpmp.httpclient.chunk-size", "-1"));	//
		}

		//if (client==null) {
			/*ClientConfig cc = new DefaultClientConfig();
			cc.getProperties().put(ClientConfig.PROPERTY_FOLLOW_REDIRECTS, true);
			cc.getProperties().put(ClientConfig.PROPERTY_READ_TIMEOUT, 3000);
			cc.getProperties().put(ClientConfig.PROPERTY_CONNECT_TIMEOUT, 3000);
			cc.getProperties().put(ClientConfig.PROPERTY_THREADPOOL_SIZE, 100);
			client = Client.create(cc);

			if (userName!=null && userName.length()>0) {
				client.addFilter(new HTTPBasicAuthFilter(userName, password==null ? "" : password));
			}*/

			DefaultApacheHttpClientConfig cc = new DefaultApacheHttpClientConfig();
			cc.getProperties().put( ApacheHttpClientConfig.PROPERTY_FOLLOW_REDIRECTS, true);
			cc.getProperties().put( ApacheHttpClientConfig.PROPERTY_THREADPOOL_SIZE, poolSize );
			cc.getProperties().put( ApacheHttpClientConfig.PROPERTY_CONNECT_TIMEOUT, connectTimout );
			cc.getProperties().put( ApacheHttpClientConfig.PROPERTY_READ_TIMEOUT, readTimeout );
			cc.getProperties().put( ApacheHttpClientConfig.PROPERTY_CHUNKED_ENCODING_SIZE, chunkSize );
			/*if (userName!=null && userName.length()>0) {
				cc.getState().setCredentials(null, null, -1, userName, password==null ? "" : password);
			}*/
			client = Client.create(cc);
			if (userName!=null && userName.length()>0) {
				client.addFilter(new HTTPBasicAuthFilter(userName, password==null ? "" : password));
			}
		//}
	}
	
	public String get(String url) {
		try {
			if (logger.isLoggable(Level.FINEST)) logger.finest("GET URL:" + url);
			WebResource wr = client.resource(UriBuilder.fromUri(url).build());
			String response = wr.accept(MediaType.APPLICATION_JSON_TYPE).get(String.class);
			if (logger.isLoggable(Level.FINEST)) logger.finest("GET response:" + response);
			return response;
		} finally {
			client.destroy();
		}
	}
	
	public String get(String url, Map<String, String> params) throws UnsupportedEncodingException {
		try {
			if (params!=null) {
				StringBuilder sb = new StringBuilder(url);
				sb.append(sb.indexOf("?")>=0 ? '&' : '?');
				int count = 0;
				for (Entry<String, String> param : params.entrySet()) {
					if (count++>0) {
						sb.append('&');
					}
					sb.append(param.getKey()).append('=')
							.append(param.getValue()!=null ? URLEncoder.encode(param.getValue(), Const.ENCODING) : "");
				}
				url = sb.toString();
			}
			if (logger.isLoggable(Level.FINEST)) logger.finest("GET URL:" + url);
			WebResource wr = client.resource(UriBuilder.fromUri(url).build());
			String response = wr.accept(MediaType.APPLICATION_JSON_TYPE).get(String.class);
			if (logger.isLoggable(Level.FINEST)) logger.finest("GET response:" + response);
			return response;
		} finally {
			client.destroy();
		}
	}
	
	public String delete(String url, Map<String, String> params) throws UnsupportedEncodingException {
		try {
			if (params!=null) {
				StringBuilder sb = new StringBuilder(url);
				sb.append(sb.indexOf("?")>=0 ? '&' : '?');
				int count = 0;
				for (Entry<String, String> param : params.entrySet()) {
					if (count++>0) {
						sb.append('&');
					}
					sb.append(param.getKey()).append('=')
							.append(param.getValue()!=null ? URLEncoder.encode(param.getValue(), Const.ENCODING) : "");
				}
				url = sb.toString();
			}
			if (logger.isLoggable(Level.FINEST)) logger.finest("DELETE URL:" + url);
			WebResource wr = client.resource(UriBuilder.fromUri(url).build());
			String response = wr.accept(MediaType.APPLICATION_JSON_TYPE).delete(String.class);
			if (logger.isLoggable(Level.FINEST)) logger.finest("DELETE response:" + response);
			return response;
		} finally {
			client.destroy();
		}
	}
	
	public String post(String url, Map<String, String> params) {
		try {
			if (logger.isLoggable(Level.FINEST)) logger.finest("POST URL:" + url);
			WebResource wr = client.resource(url);
			MultivaluedMap<String, String> map = new MultivaluedMapImpl();
			if (params!=null) {
				for (Entry<String, String> param : params.entrySet()) {
					if (param.getValue()!=null) {
						map.add(param.getKey(), param.getValue().toString());
					}
				}
			}
			String response = wr.accept(MediaType.APPLICATION_JSON_TYPE)
					.type(MediaType.APPLICATION_FORM_URLENCODED).post(String.class, map);
			if (logger.isLoggable(Level.FINEST)) logger.finest("POST response:" + response);
			return response;
		} finally {
			client.destroy();
		}
	}
    
	public String post(String url, JSONObject params) {
		try {
			if (logger.isLoggable(Level.FINEST)) logger.finest("POST URL:" + url);
			WebResource wr = client.resource(url);
			MultivaluedMap<String, String> map = new MultivaluedMapImpl();
			if (params!=null) {
				for (Entry<String, Object> param : params.entrySet()) {
					if (param.getValue()!=null) {
						map.add(param.getKey(), param.getValue().toString());
					}
				}
			}
			String response = wr.accept(MediaType.APPLICATION_JSON_TYPE)
					.type(MediaType.APPLICATION_FORM_URLENCODED).post(String.class, map);
			if (logger.isLoggable(Level.FINEST)) logger.finest("POST response:" + response);
			return response;
		} finally {
			client.destroy();
		}
	}
	
	public String put(String url, Map<String, String> params) {
		try {
			if (logger.isLoggable(Level.FINEST)) logger.finest("PUT URL:" + url);
			WebResource wr = client.resource(url);
			MultivaluedMap<String, String> map = new MultivaluedMapImpl();
			if (params!=null) {
				for (Entry<String, String> param : params.entrySet()) {
					if (param.getValue()!=null) {
						map.add(param.getKey(), param.getValue().toString());
					}
				}
			}
			String response = wr.accept(MediaType.APPLICATION_JSON_TYPE)
					.type(MediaType.APPLICATION_FORM_URLENCODED).put(String.class, map);
			if (logger.isLoggable(Level.FINEST)) logger.finest("PUT response:" + response);
			return response;
		} finally {
			client.destroy();
		}
	}
	
	public String put(String url, JSONObject params) {
		try {
			if (logger.isLoggable(Level.FINEST)) logger.finest("PUT URL:" + url);
			WebResource wr = client.resource(url);
			MultivaluedMap<String, String> map = new MultivaluedMapImpl();
			if (params != null) {
				for (Entry<String, Object> param : params.entrySet()) {
					if (param.getValue() != null) {
						map.add(param.getKey(), param.getValue().toString());
					}
				}
			}
			String response = wr.accept(MediaType.APPLICATION_JSON_TYPE)
					.type(MediaType.APPLICATION_FORM_URLENCODED).put(String.class, map);
			if (logger.isLoggable(Level.FINEST)) logger.finest("PUT response:" + response);
			return response;
		} finally {
			client.destroy();
		}
	}

	/**
	 * @param args
	 * @throws UnsupportedEncodingException 
	 */
	public static void main(String[] args) throws UnsupportedEncodingException {
		Date s = new Date();
		JerseyRestClient c = new JerseyRestClient("admin", "admin");
		//String o = c.get("http://localhost:8090/bpmp//servlet/co?action=queryCoTasks");
		
		/*JSONObject jo = new JSONObject();
		jo.put("aaa", "postpost");
		jo.put("fromRow", "200");
		
		Map<String, String> jo1 = new HashMap<String, String>();
		jo1.put("params", "getget");
		jo1.put("fromRow", "100");*/
		String o = c.get("http://localhost:8091/bpmp-engine/api/v1/engine/bpdWithVersion/FLOW-70c0ec1c-1b5d-4a4d-aaea-01d12eab989b/4?timezoneOffset=-480&_=1499938649943", null);
		//String o = c.post("http://localhost:8090/bpmp/openrest/co/test", jo);
		//String o = c.put("http://localhost:8090/bpmp/openrest/co/testdel", jo);
		//String o = c.delete("http://localhost:8090/bpmp/openrest/co/testdel", jo1);
		logger.info(o);
		Date e = new Date();
		logger.info("Used "+(e.getTime()-s.getTime())+" milliseconds.");
	}

}
